by Gene Olafsen
In This Chapter
MFC provides a powerful set of classes, macros, and global functions to provide access to a sizeable portion of the vast OLE empire.
The MFC framework prefixes global public functions with the letters Afx. These functions are available to you whether you develop an EXE-based (CWinApp-derived) application or a DLL-based (COleControlModule-derived) object server. There are little more than two dozen Afx functions, and they basically all either perform initialization operations or offer some kind of object lifetime support.
A number of functions are globally available to an MFC-based application or DLL that enable you to control the circumstances under which the program will terminate or the DLL will unload.
AfxOleCanExitApp
The AfxOleCanExitApp function returns a Boolean value indicating whether or not the application can terminate. The AfxOleLockApp and AfxOleUnlockApp functions increment and decrement, respectively, the m_nObjectCount variable. This function simply returns a value based on the state of that counter.
BOOL AFXAPI AfxOleCanExitApp()
{
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
return pModuleState->m_nObjectCount == 0;
}
In addition, this method is called internally by the MFC framework to determine whether an application can terminate or an OLE-server DLL can unload.
SCODE AFXAPI AfxDllCanUnloadNow(void)
{
// return S_OK only if no outstanding objects active
if (!AfxOleCanExitApp())
return S_FALSE;
// check if any class factories with >1 reference count
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
}
AfxOleGetMessageFilter
The AFxOleGetMessageFilter retrieves the application objects current message filter. The message filter object that this function returns derives from the COleMessageFilter class.
_AFXWIN_INLINE COleMessageFilter* AFXAPI AfxOleGetMessageFilter()
{
ASSERT_VALID(AfxGetThread());
return AfxGetThread()->m_pMessageFilter;
}
AfxOleGetUserCtrl
The AfxOleGetUserCtrl function retrieves the current state of the user-control flag. When the application was launched by the OLE system DLLs, the user is not considered in control; thus this function returns a FALSE value. Such a condition exists when the application is launched with command-line arguments that indicate the conditions under which the application was started. The companion set function (AfxOleSetUserCtrl) is seen setting the variable retrieved by this function to FALSE under those conditions where the application is launched with such arguments.
void CCommandLineInfo::ParseParamFlag(const char* pszParam)
{
// OLE command switches are case insensitive, while
// shell command switches are case sensitive
if (lstrcmpA(pszParam, pt) == 0)
m_nShellCommand = FilePrintTo;
else if (lstrcmpA(pszParam, p) == 0)
m_nShellCommand = FilePrint;
else if (lstrcmpiA(pszParam, Unregister) == 0 ||
lstrcmpiA(pszParam, Unregserver) == 0)
m_nShellCommand = AppUnregister;
else if (lstrcmpA(pszParam, dde) == 0)
{
AfxOleSetUserCtrl(FALSE);
m_nShellCommand = FileDDE;
}
else if (lstrcmpiA(pszParam, Embedding) == 0)
{
AfxOleSetUserCtrl(FALSE);
m_bRunEmbedded = TRUE;
m_bShowSplash = FALSE;
}
else if (lstrcmpiA(pszParam, Automation) == 0)
{
AfxOleSetUserCtrl(FALSE);
m_bRunAutomated = TRUE;
m_bShowSplash = FALSE;
}
}
Otherwise, the code for the AfxOleGetUserCtrl function is very straightforward, returning the value of a global variable.
BOOL AFXAPI AfxOleGetUserCtrl()
{
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
return pModuleState->m_bUserCtrl;
}
AfxOleSetUserCtrl
The AfxOleSetUserCtrl function accepts a Boolean argument, and you can use it to set or clear the user-control flag. The conditions under which this flag is called are described in more detail in the previous section.
It is interesting to note, however, the framework code that implements this function. In the debug build of the libraries, the application does not shut down if you have obtained control of the application.
void AFXAPI AfxOleSetUserCtrl(BOOL bUserCtrl)
{
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
#ifdef _DEBUG
CWinApp* pApp = AfxGetApp();
if (bUserCtrl && !pModuleState->m_bUserCtrl &&
(pApp == NULL || pApp->m_pMainWnd == NULL ||
!pApp->m_pMainWnd->IsWindowVisible()))
{
// If the user gets control while the application window is
// not visible, the application may not shut down when the object
// count reaches zero.
TRACE0(Warning: AfxOleSetUserCtrl(TRUE) called \
with application window hidden.\n);
}
#endif
pModuleState->m_bUserCtrl = bUserCtrl;
}
AfxOleLockApp
The AfxOleLockApp function increments a global lock count variable. MFC keeps track of the number of OLE objects that are active and calls this function accordingly. The framework uses the InterlockedIncrement function to adjust the value of the pModuleState->m_nObjectCount variable. This function synchronizes access to a variable and prevents more than one thread from accessing that variable simultaneously.
void AFXAPI AfxOleLockApp()
{
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
InterlockedIncrement(&pModuleState->m_nObjectCount);
}
AfxOleUnlockApp
The AfxOleUnlockApp function is the counter-function to AfxOleLockApp. This function decrements the frameworks object counter variable in a thread-safe manner.
void AFXAPI AfxOleUnlockApp()
{
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
ASSERT(pModuleState->m_nObjectCount != 0);
if (InterlockedDecrement(&pModuleState->m_nObjectCount) == 0)
{
// allow application to shut down when all the objects have
// been released
::AfxOleOnReleaseAllObjects();
}
}
AfxOleRegisterServerClass
The AfxOleRegisterServerClass function provides a mechanism for you to register your server in the system Registry. The function takes a large number of parameters, but the gist of this functions purpose is to provide more control over the registration process than the Register function in COleTemplateServer offers.